var DownloadManager = Base.extend({
	constructor: null,
	download: [],
	download_map: {},
	download_available: 1,
	downloading_count: 0,

	_NextID: function()
	{
		return this.download_available;
	},
	_Add: function(obj)
	{
		var ret;

		ret = this.download_available;
		this.download[ret] = obj;
		for(;this.download[this.download_available];) this.download_available++;
		Debug.trace(2,'DownloadManager: download=(%s), download_available=%d, downloading_count=%d',this.download,this.download_available,this.downloading_count);
		return ret;
	},
	_Remove: function(id)
	{
		this.download[id] = null;
		if(id < this.download_available) this.download_available = id;
		if(this.download_available == 0) this.download_available = 1;
		Debug.trace(2,'DownloadManager: download=(%s), download_available=%d, downloading_count=%d',this.download,this.download_available,this.downloading_count);
	},
	NewDownload: function(url,callback,userdata,noid)
	{
		var url;
		var obj = {};
		var id;
		var node;

		if(callback) obj.callback = callback;
		if(userdata) obj.userdata = userdata;
		id = this._Add(obj);
		
		node = document.createElement('script');
		node.type = 'text/javascript';

		if(!noid) url = url + '&download_callback_id=' + id;

		node.src = url;

		Debug.trace(0,'DownloadManager: Start downloading (%d) from <a href="' + url + '">' + url + '</a>',id);
		document.body.appendChild(node);
		this.downloading_count++;
		return id;
	},
	NewDownloadName: function(name,url,callback,userdata)
	{
		var url;
		var obj = {};
		var node;

		if(callback) obj.callback = callback;
		if(userdata) obj.userdata = userdata;
		this.download_map[name] = obj;

		node = document.createElement('script');
		node.type = 'text/javascript';
		node.src = url;

		Debug.trace(0,'DownloadManager: Start downloading (%s) from <a href="' + url + '">' + url + '</a>',name);
		document.body.appendChild(node);
		this.downloading_count++;
		return name;
	},
	CancelDownload: function(id)
	{
		Debug.trace(4,'DownloadManager: Download id=%d cancel.',id);
		this._Remove(id);
		this.downloading_count--;
	},
	CancelDownloadName: function(name)
	{
		Debug.trace(4,'DownloadManager: Download name=%s cancel.',name);
		this.download_map[name] = null;
		this.downloading_count--;
	},
	ServerCallbackName: function(name,data)
	{
		var obj;

		obj = this.download_map[name];
		if(obj) {
			Debug.trace(1,'DownloadManager: Download name=%s completed.',name);
			obj.callback(obj.userdata,data);
			this.downloading_count--;
		}
		else {
			Debug.trace(1,'DownloadManager: Invalid callback name=%s (maybe cancelled)',name);
		}
	},
	ServerCallback: function(id,data)
	{
		var obj;

		obj = this.download[id];
		if(obj) {
			Debug.trace(1,'DownloadManager: Download id=%d completed.',id);
			this._Remove(id);
			obj.callback(obj.userdata,data);
			this.downloading_count--;
		}
		else {
			Debug.trace(1,'DownloadManager: Invalid callback id=%d (maybe cancelled)',id);
		}
	}
});

var ProgressiveObject = Base.extend({
	constructor: function()
	{
	},
	onCompleteComponent: function(name)
	{
		return true;
	},
	onErrorComponent: function(name)
	{
		return true;
	},
	GetClass: function()
	{
		return ProgressiveObject;
	},
	DownloadComponent: function(name)
	{
		var _this = this;
		var data = {};
		if(!_this.component_src[name]) return;

		data.name = name;
		data._this = _this;
		data.x = this;

		DownloadManager.NewDownload(_this.component_src[name],
		function(userdata,serverdata) {
			if(serverdata) {
				for(var key in serverdata) {
					if(key == 'dummy') continue;
					userdata._this[key] = serverdata[key];
				}
				userdata._this.component_src[userdata.name] = null;
				userdata.x.onCompleteComponent(userdata.name);
			}
			else userdata.x.onErrorComponent(userdata.name);
		},data);
	},
	DownloadComponentStatic: function(name)
	{
		var data = {};
		var _this = this.GetClass();

		if(!_this.component_src[name]) return;

		data.name = name;
		data._this = _this;
		data.x = this;
		
		DownloadManager.NewDownload(_this.component_src[name],
		function(userdata,serverdata) {
			if(serverdata) {
				for(var key in serverdata) {
					if(key == 'dummy') continue;
					userdata._this[key] = serverdata[key];
				}
				userdata._this.component_src[userdata.name] = null;
				userdata.x.onCompleteComponent(userdata.name);
			}
			else userdata.x.onErrorComponent(userdata.name);
		},data);
	}
});
